﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using ConvertLib.ZlibCompress;
using SHVS.Components.BuildingEdit;
using SHVS.Generation;
using VLIB28D.Geometry3D;
using VLIB2D.Geometry2D;

namespace GMPP
{
    public class BuildingEdit
    {
        private Point3D _center = new Point3D();

        private Podetium _groundFloor;
        private Podetium _mainFloor;

        private Roof _roof;

        private List<EditTexture> _texList;
        private string _titleName;


        public BuildingEdit(byte[] bytes)
        {
            TexList = new List<EditTexture>();
            byte[] unComBytes = ZlibComp.DiscodeZlibCom(bytes);
            using (var ms = new MemoryStream(unComBytes))
            {
                ms.Position = 0;
                using (var br = new BinaryReader(ms))
                {
                    _center.X = br.ReadDouble();
                    _center.Y = br.ReadDouble();
                    _center.Z = br.ReadDouble();
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        _titleName = ReadString(br, 10, "gb2312");
                        switch (_titleName.ToUpper())
                        {
                            case "MAIN":
                                _mainFloor = ParsePodetium(br, _titleName);
                                break;
                            case "SHOP":
                                _groundFloor = ParsePodetium(br, _titleName);
                                break;
                            case "ROOF":
                                _roof = ParseRoof(br, _titleName);
                                break;
                            case "TEX":
                                ParseTexs(br);

                                break;
                        }
                    }
                }
            }
        }

        public List<EditTexture> TexList
        {
            get { return _texList; }

            set { _texList = value; }
        }

        public Point3D Center
        {
            get { return _center; }
            set { _center = value; }
        }

        public string TitleName
        {
            get { return _titleName; }
            set { _titleName = value; }
        }


        private static Podetium ParsePodetium(BinaryReader br, string title)
        {
            var pod = new Podetium {Title = title};

            int faceNum = br.ReadInt32();
            for (int j = 0; j < faceNum; j++)
            {
                int ptNum = br.ReadInt32();
                var face = new SideFace { Title = title, Index = j };

                for (int pNum = 0; pNum < ptNum; pNum++)
                {
                    var p = new Point3D { X = br.ReadDouble(), Y = br.ReadDouble(), Z = br.ReadDouble() };
                    face.Points.Add(p);
                }

                for (int pNum = 0; pNum < ptNum; pNum++)
                {
                    var p = new Point2D { X = br.ReadDouble(), Y = br.ReadDouble() };

                    face.UvPts.Add(p);
                }

                face.TexName = ReadString(br, 20, "gb2312");
                //face.Update();
                pod.Sides.Add(face);
            }


            return pod;
        }


        public static Roof ParseRoof(BinaryReader br, String title)
        {
            int tNum = br.ReadInt32();
            var roof = new Roof {Title = title, TexName = ReadString(br, 20, "gb2312")};

            for (int i = 0; i < tNum; i++)
            {
                var t = new Triangle3D();
                for (int j = 0; j < 3; j++)
                {
                    t[j].X = br.ReadDouble();
                    t[j].Y = br.ReadDouble();
                    t[j].Z = br.ReadDouble();
                    roof.PointTrian.Add(t);
                }
            }

            for (int i = 0; i < tNum; i++)
            {
                var t = new Triangle2D();
                for (int j = 0; j < 3; j++)
                {
                    t[j].X = br.ReadDouble();
                    t[j].Y = br.ReadDouble();

                    roof.UvTrian.Add(t);
                }
            }
            return roof;
        }

        public void ParseTexs(BinaryReader br)
        {
            int texNum = br.ReadInt32();

            for (int i = 0; i < texNum; i++)
            {
                string texName = ReadString(br, 20, "gb2312");
                int len = br.ReadInt32();
                int width = br.ReadInt32();
                int height = br.ReadInt32();


                byte[] by = br.ReadBytes(len);
                var img = byteArrayToImage(by);

               

                var bitmap = new Bitmap(img);

                //var sp = new ShowPic(img);
                

                var tex = new EditTexture(texName, bitmap);

                _texList.Add(tex);
            }
        }


        private Image byteArrayToImage(byte[] Bytes)
        {
            using (var ms = new MemoryStream(Bytes))
            {
                Image outputImg = Image.FromStream(ms);
                return outputImg;
            }
        }

        public static string ReadString(BinaryReader br, int length, string encoding)
        {
            byte[] bytes = br.ReadBytes(length);
            string str = Encoding.GetEncoding(encoding).GetString(bytes);
            str = str.TrimEnd('\0');
            return str;
        }
    }
}